package br.ufrj.arquitetura.teste;

import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;

import br.ufrj.arquitetura.Arquitetura;
import br.ufrj.arquitetura.Instrucao;

public class ArquiteturaTeste {

	@Ignore
	@Test
	public void test() {
		Instrucao instrucao = new Instrucao(0, "jmp", "5");
		Assert.assertEquals(1, instrucao.numeroDeParametros());
		
		System.out.println(Integer.decode("0x400"));
		
		Assert.assertTrue("Nao eh registrador", Arquitetura.ehRegistrador("R6"));
	}
	
	@Test
	public void testaSomaConstanteRegistrador() {
		// Criar uma instrucao 2 + 3
		Arquitetura.reg2 = 3;
		Instrucao i = new Instrucao(0, "add", "2", "R2");
		// executar a instrucao
		Arquitetura.executaInstrucao(i);
		
		Assert.assertEquals(5, Arquitetura.reg2);
		
	}
	
	@Test
	public void testaAssert(){
		Assert.assertTrue(Arquitetura.ehMemoria("(R2)"));
	}

	@Test
	public void testaJump(){
		
		Instrucao i = new Instrucao(0, "jmp", "2");
		Instrucao i1 = new Instrucao(1, "mov", "2", "R1");
		Instrucao i2 = new Instrucao(2, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(3, "mov", "2", "R3");
		
		Arquitetura.memoria[0] = i;
		Arquitetura.memoria[1] = i1;
		Arquitetura.memoria[2] = i2;
		Arquitetura.memoria[3] = i3;
		
		Arquitetura.executaInstrucao(i);
		Assert.assertEquals(2, Arquitetura.pc);
	}
		
	@Test
	public void testeAddConstanteRegistrador() 
	{

		Instrucao i2 = new Instrucao(2, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(3, "add", "3", "R2");
		
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(5, Arquitetura.reg2);


	}
	
	@Test
	public void testeAddRegistradorRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "2", "R1");
		Instrucao i2 = new Instrucao(2, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(3, "add", "R1", "R2");

		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(4, Arquitetura.reg2);
	}
	
	@Test
	public void testeAddMemoriaRegistrador() 
	{
		Instrucao i0 = new Instrucao(1, "mov", "0", "R1");
		Instrucao i1 = new Instrucao(1, "mov", "2", "(R1)");
		Instrucao i2 = new Instrucao(2, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(3, "add", "(R1)", "R2");
		
		Arquitetura.executaInstrucao(i0);
		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(4, Arquitetura.reg2);
		
	}
	
	@Test
	public void testeMovConstanteRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "2", "R1");
		Arquitetura.executaInstrucao(i1);
		Assert.assertEquals(2, Arquitetura.reg1);
		
	}

	@Test
	public void testeSubConstanteRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "2", "R1");
		Instrucao i2 = new Instrucao(2, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(3, "sub", "R1", "R2");

		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(0, Arquitetura.reg2);
		
	}
	
	@Test
	public void testeCmpConstanteRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "2", "R1");
		Instrucao i2 = new Instrucao(2, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(3, "cmp", "2", "R2");

		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(1, Arquitetura.getFlagZ());
	}
	
	@Test
	public void testeAndRegistradorRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "2", "R1");
		Instrucao i2 = new Instrucao(2, "mov", "4", "R2");
		Instrucao i3 = new Instrucao(3, "and", "R1", "R2");

		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(0, Arquitetura.reg2);
		
	}
	
	@Test
	public void testeOrRegistradorRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "2", "R1");
		Instrucao i2 = new Instrucao(2, "mov", "4", "R2");
		Instrucao i3 = new Instrucao(3, "or", "R1", "R2");

		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(6, Arquitetura.reg2);
		
	}
	
	@Test
	public void testeNotRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "0", "R1");
//		Instrucao i2 = new Instrucao(2, "mov", "4", "R2");
		Instrucao i3 = new Instrucao(3, "not", "R1");

		Arquitetura.executaInstrucao(i1);
	//	Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(-1, Arquitetura.reg1);
		
	}

	@Test
	public void testeClrRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "3", "R1");
//		Instrucao i2 = new Instrucao(2, "mov", "4", "R2");
		Instrucao i3 = new Instrucao(3, "clr", "R1");

		Arquitetura.executaInstrucao(i1);
	//	Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(0, Arquitetura.reg1);
		
	}
	
	@Test
	public void testeNegRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "8", "R1");
//		Instrucao i2 = new Instrucao(2, "mov", "4", "R2");
		Instrucao i3 = new Instrucao(3, "neg", "R1");

		Arquitetura.executaInstrucao(i1);
	//	Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(-8, Arquitetura.reg1);
		
	}

	@Test
	public void testeShlRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "1", "R1");
//		Instrucao i2 = new Instrucao(2, "mov", "4", "R2");
		Instrucao i3 = new Instrucao(3, "shl", "R1");

		Arquitetura.executaInstrucao(i1);
	//	Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(2, Arquitetura.reg1);
		
	}
	
	@Test
	public void testeShrRegistrador() 
	{
		Instrucao i1 = new Instrucao(1, "mov", "2", "R1");
//		Instrucao i2 = new Instrucao(2, "mov", "4", "R2");
		Instrucao i3 = new Instrucao(3, "shr", "R1");

		Arquitetura.executaInstrucao(i1);
	//	Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Assert.assertEquals(1, Arquitetura.reg1);
		
	}
	
	@Test
	public void testeBrzRegistrador() 
	{
		Instrucao i1 = new Instrucao(0, "mov", "2", "R1");
		Instrucao i2 = new Instrucao(1, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(2, "sub", "R1","R2");
		Instrucao i4 = new Instrucao(3, "brz", "1");

		Arquitetura.memoria[0] = i1;
		Arquitetura.memoria[1] = i2;
		Arquitetura.memoria[2] = i3;
		Arquitetura.memoria[3] = i4;
		
		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Arquitetura.executaInstrucao(i4);
		
		Assert.assertEquals(1, Arquitetura.getFlagZ());
		
	}	

	@Test
	public void testeBrnRegistrador() 
	{
		Instrucao i1 = new Instrucao(0, "mov", "-2", "R1");
		Instrucao i2 = new Instrucao(1, "mov", "-3", "R2");
		Instrucao i3 = new Instrucao(2, "sub", "R1","R2");
		Instrucao i4 = new Instrucao(3, "brn", "-3");

		Arquitetura.memoria[0] = i1;
		Arquitetura.memoria[1] = i2;
		Arquitetura.memoria[2] = i3;
		Arquitetura.memoria[3] = i4;
		
		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Arquitetura.executaInstrucao(i4);
		
		Assert.assertEquals(1, Arquitetura.getFlagN());
		
	}
	
	@Test
	public void testeBreRegistrador() 
	{
		Instrucao i1 = new Instrucao(0, "mov", "2", "R1");
		Instrucao i2 = new Instrucao(1, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(2, "cmp", "R1","R2");
		Instrucao i4 = new Instrucao(3, "bre", "1");

		Arquitetura.memoria[0] = i1;
		Arquitetura.memoria[1] = i2;
		Arquitetura.memoria[2] = i3;
		Arquitetura.memoria[3] = i4;
		
		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Arquitetura.executaInstrucao(i4);
		
		Assert.assertEquals(1, Arquitetura.getFlagZ());		
	}	

	@Test
	public void testeBrlRegistrador() 
	{
		Instrucao i1 = new Instrucao(0, "mov", "1", "R1");
		Instrucao i2 = new Instrucao(1, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(2, "cmp", "R2","R1");
		Instrucao i4 = new Instrucao(3, "brl", "1");

		Arquitetura.memoria[0] = i1;
		Arquitetura.memoria[1] = i2;
		Arquitetura.memoria[2] = i3;
		Arquitetura.memoria[3] = i4;
		
		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Arquitetura.executaInstrucao(i4);
		
		Assert.assertEquals(1, Arquitetura.getFlagN());
		
	}	
		
	@Test
	public void testeBrgRegistrador() 
	{
		Instrucao i1 = new Instrucao(0, "mov", "3", "R1");
		Instrucao i2 = new Instrucao(1, "mov", "2", "R2");
		Instrucao i3 = new Instrucao(2, "cmp", "R2","R1");
		Instrucao i4 = new Instrucao(3, "brg", "1");

		Arquitetura.memoria[0] = i1;
		Arquitetura.memoria[1] = i2;
		Arquitetura.memoria[2] = i3;
		Arquitetura.memoria[3] = i4;
		
		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Arquitetura.executaInstrucao(i4);
		
		Assert.assertEquals(0, Arquitetura.getFlagN());
		
	}	
		
	@Test
	public void testeAddRegistradorMemoria() 
	{
		Instrucao i1 = new Instrucao(0, "mov", "3", "R1");
		Instrucao i2 = new Instrucao(1, "mov", "14", "R2");
		Instrucao i3 = new Instrucao(2, "mov", "3","(R2)");
		Instrucao i4 = new Instrucao(3, "add", "R1","(R2)");

		Arquitetura.memoria[0] = i1;
		Arquitetura.memoria[1] = i2;
		Arquitetura.memoria[2] = i3;
		Arquitetura.memoria[3] = i4;
		
		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Arquitetura.executaInstrucao(i4);

		Assert.assertEquals(6, Arquitetura.getConteudoMemoria("(R2)"));

	}

	@Test
	public void testeSubRegistradorMemoria() 
	{
		Instrucao i1 = new Instrucao(0, "mov", "3", "R1");
		Instrucao i2 = new Instrucao(1, "mov", "14", "R2");
		Instrucao i3 = new Instrucao(2, "mov", "3","(R2)");
		Instrucao i4 = new Instrucao(3, "sub", "R1","(R2)");

		Arquitetura.memoria[0] = i1;
		Arquitetura.memoria[1] = i2;
		Arquitetura.memoria[2] = i3;
		Arquitetura.memoria[3] = i4;
		
		Arquitetura.executaInstrucao(i1);
		Arquitetura.executaInstrucao(i2);
		Arquitetura.executaInstrucao(i3);
		Arquitetura.executaInstrucao(i4);

		Assert.assertEquals(0, Arquitetura.getConteudoMemoria("(R2)"));

	}

}
